(function(){
	var jsTextTemplateBefore = [
	  "  var __worker__ = this;",
	  "  function postMessage(message) {",
	  "    __worker__._receiveMessage(message);",
	  "  };",
	  "  __worker__._onmessageHandler = function() {",
	  "    var message;",
	  "    while (message = __worker__._messageQueue.shift()) {",
	  "      try {",
	  "        onmessage && onmessage.call(null, {'data' : message});",
	  "      }catch(e){",
	  "         __worker__._lastError = e;",
	  "      }",
	  "    }",
	  "    __worker__._handleError();",
	  "    if (!__worker__._aboutToTerminate) {",
	  "      __worker__._timeoutId = window.setTimeout(arguments.callee, 1000);",
	  "    }",
	  "  };"
	].join("");
	
	function Worker(jsText, onmessage, onerror) {
		this._messageQueue = [];
		this._onmessage = onmessage;
		this._onerror = onerror;
		this._lastError = null;
		
		var text = jsTextTemplateBefore + jsText;
		var runner = new Function(text);
		runner.apply(this);
		
		this._aboutToTerminate = false;
		this._timeoutId = window.setTimeout(this._onmessageHandler, 0);
	}
	
	Worker.prototype = {
		postMessage : function(message) {
			message && this._messageQueue.push(message);
		},
		
		terminate : function() {
			//process all messages before termination
			this._aboutToTerminate = true;
			this._onmessageHandler();
			window.clearTimeout(this._timeoutId);
		},
		
		_receiveMessage : function(message) {
			this._onmessage.apply(this, [{"data" : message}]);
		},
		
		_handleError : function() {
			this._lastError && this._onerror && this._onerror.apply(this, [this._lastError]);
		},
		
		getName : function() {
			return "TimeoutWorker";
		}
	};
	
    JsWorker.TimeoutWorker = {
        createWorkerFromUrl: function(jsUrl, onmessage, onerror){
			var jsText = fetchScriptText(jsUrl);
			return new Worker(jsText, onmessage, onerror);
        }
    };
	
})();
